<!-- 发送框 -->
<template>
  <div class="chat-editor">
    <input
      style="display: none"
      type="file"
      multiple="multiple"
      ref="fileInput"
      :accept="accept"
      @change="handleChangeFile"
    />
    <div class="chat-editor__tool">
      <el-popover ref="emojiPopover" title="" width="365" trigger="click">
        <div class="emoji_box">
          <div
            class="emoji_item"
            v-for="(emoji, index) in emoji_list"
            :key="index"
            @click="handleEmojiClick(emoji)"
          >
            <img :src="emoji" />
          </div>
        </div>
        <div style="padding-top: 5px" slot="reference">
          <svg-icon iconClass="emoji" className="icon"></svg-icon>
        </div>
      </el-popover>

      <template>
        <svg-icon
          v-for="icon in icons"
          :key="icon"
          :iconClass="icon"
          @click="handleToolClick(icon)"
          className="icon"
        ></svg-icon>
      </template>

      <input
        style="display: none"
        type="file"
        multiple="multiple"
        ref="fileInput"
        @change="_handleChangeFile"
      />
    </div>
    <div class="chat-editor__inner">
      <div
        class="chat-editor__input"
        ref="textarea"
        @drop="_handleDrop"
        @keyup="_handleKeyup"
        @paste.prevent="_handlePaste"
        @input="_handleInput"
        @keydown="_handleKeydown"
        spellcheck="false"
      />
    </div>
    <div class="chat-editor__footer">
      <div class="chat-editor__tip">Enter发送，Ctrl + enter换行</div>
      <div class="chat-editor__submit">
        <el-button
          :disabled="submitDisabled"
          type="primary"
          size="small"
          @click="_handleSend"
          >发送</el-button
        >
      </div>
    </div>
    <div
      v-if="
        currentChatInfo.status &&
        currentChatInfo.status !== CHAT_STATUS.NORMAL &&
        isSiderChat
      "
      class="disabled-info_box"
    >
      <span v-if="currentChatInfo.status === CHAT_STATUS.NOT_IN_GROUP">
        <i class="el-icon-warning-outline"></i> 无法在已退出群聊中发送消息
      </span>
      <span v-else>
        <i class="el-icon-warning-outline"></i>无法在已解散群聊中发送消息
      </span>
    </div>
  </div>
</template>

<script>
const command = (command, val) => {
  document.execCommand(command, false, val)
}

import ScreenShot from "js-web-screen-shot"
import ChatArea from "chatarea"
// 引入css样式
import "chatarea/lib/ChatArea.css"
import { mapGetters, mapState } from "vuex"
import { CHAT_STATUS, MESSAGE_TYPE } from "@/utils/constant"
import lockr from "lockr"
// import { clearHtmlExcludeImg } from "@/utils"
export default {
  name: "editPage",
  data() {
    return {
      accept: "",
      chatArea: null,
      clipboardBlob: null,
      clipboardUrl: null,
      submitDisabled: true,
      CHAT_STATUS,
      timeoutList: [],
      setting: {
        sendKey: 1
      },
      emoji_list: new Array(63).fill(0).map((item, index) => {
        // eslint-disable-next-line no-undef
        return minioEndpoint_mini + `emoji/jj_emoji_${index + 1}.png`
      }),
      icons: ["folder", "time"]
      // icons: ["folder"]
    }
  },

  computed: {
    ...mapGetters(["currentGroupMemberList"]),
    ...mapState(["currentChatInfo", "userInfo"]),
    isSiderChat() {
      return this.$route.path !== "/chat"
    }
  },

  created() {
    this.$nextTick(() => {
      this.chatArea = new ChatArea({
        elm: this.$refs.textarea, // 从dom上抓取一个元素将其改造
        userList: [],
        userProps: {
          // 人员列表数据结构 转接差异key值
          id: "id",
          name: "name",
          avatar: "avatar"
        },
        placeholder: "",
        needCallSpace: true,
        wrapKeyFun: (event) => this.wrapKey(event),
        sendKeyFun: (event) => this.sendKey(event)
      })
      this.updateUserList()
      this.chatArea.richText.addEventListener("blur", () => {
        setTimeout(this.chatArea.winClick, 200)
      })

      // 监听发送键
      this.chatArea.enterSend = () => {
        // 在此处执行你对发送消息的处理
        if (this.submitDisabled == false) {
          this._handleSend()
        }
      }
      //监听默认事件
      this.chatArea.addEventListener("defaultAction", (type, e) => {
        if (type == "PASTE") {
          console.log("粘贴", e)
          console.log(type)
          // this._handlePaste()
          return "PREVENT"
        }
      })
    })
  },

  methods: {
    handleChangeFile() {},
    _handleKeyup() {
      this._checkSubmitDisabled()
    },
    _handleKeydown(e) {
      if (e.keyCode == 13 || (e.keyCode == 13 && e.shiftKey)) {
        e.preventDefault()
      }
      if (this.wrapKey(e)) {
        e.preventDefault()
        command("insertLineBreak")
      }
    },

    _handleInput() {
      this._checkSubmitDisabled()
    },
    _checkSubmitDisabled() {
      this.submitDisabled = this.chatArea.isEmpty()
    },
    //发送
    _handleSend() {
      const content = this.getFormatValue()
      this.$emit("send", content)
      this.clear()
      this._checkSubmitDisabled()
    },

    //清空输入框内容
    clear() {
      this.chatArea.clear()
    },
    //获取输入框内容
    getFormatValue() {
      const contentText = this.chatArea.getHtml().replace(/<(?!img)[^>]*>/g, "")
      const content = this.chatArea.getHtml()
      const atTargetIds = this.chatArea
        .getCallUserList()
        .map((item) => item.id)
        .join(",")
      const type =
        atTargetIds && atTargetIds.length > 0
          ? MESSAGE_TYPE.AT
          : MESSAGE_TYPE.TEXT
      return {
        contentText,
        content,
        atTargetIds: atTargetIds === "isALL" ? "ALL" : atTargetIds,
        type
      }
    },

    wrapKey(e) {
      return this.setting.sendKey == 1
        ? e.keyCode == 13 && e.ctrlKey
        : e.keyCode == 13 && !e.ctrlKey && !e.shiftKey
    },
    // 设置发送键
    sendKey(e) {
      return this.setting.sendKey == 1
        ? e.keyCode == 13 && !e.ctrlKey && !e.shiftKey
        : e.keyCode == 13 && e.ctrlKey
    },
    /**
     * 粘贴触发
     * @param {*} e
     */
    async _handlePaste(e) {
      e.preventDefault()
      const clipboardData = e.clipboardData || window.clipboardData
      if (this.hasImages(clipboardData)) {
        const { blob, blobUrl } = this._getClipboardBlob(clipboardData)
        this.clipboardBlob = blob
        this.clipboardUrl = blobUrl
        this.confirmSendImage(blob, blobUrl)
      }

      if (this.handFiles(clipboardData)) {
        const files = clipboardData.files
        for (let i = 0; i < files.length; i++) {
          if (!files[i].type.startsWith("image/")) {
            this.$emit("upload", files[i])
          }
        }
      }
      if (this.hasText(clipboardData)) {
        const text = clipboardData.getData("text/plain").trim()
        // 匹配 <img> 标签（包括自闭合标签）
        const regex = /(<img\s+[^>]*\/?>)/
        // 分割并过滤空字符串
        const arr = text.split(regex).filter((part) => part.trim() !== "")
        arr.forEach((item) => {
          if (item.startsWith("<img")) {
            this.chatArea.insertHtml(item)
          } else {
            this.chatArea.insertText(item)
          }
        })
      }
      this._checkSubmitDisabled()
    },
    splitTextAndImages(str) {
      // 匹配 <img> 标签（包括自闭合标签）
      const regex = /(<img\s+[^>]*\/?>)/
      // 分割并过滤空字符串
      return str.split(regex).filter((part) => part.trim() !== "")
    },
    handFiles(clipboardData) {
      return clipboardData.files.length > 0
    },
    hasImages(clipboardData) {
      return Array.from(clipboardData.items).some(
        (item) => item.kind === "file" && item.type.startsWith("image/")
      )
    },
    hasText(clipboardData) {
      return clipboardData.getData("text/plain").trim().length > 0
    },
    _handleDrop(e) {
      e.preventDefault()
      const { dataTransfer } = e
      const { files } = dataTransfer
      Array.from(files).forEach((file) => {
        this.$emit("upload", file)
      })
    },

    confirmSendImage(file, fileUrl) {
      this.$confirm(
        "<img src=" +
          fileUrl +
          ' style="width:390px;height:100%;max-height:360px;object-fit:contain">',
        "发送截图",
        {
          dangerouslyUseHTMLString: true,
          confirmButtonText: "发送",
          showCancelButton: true,
          callback: (action, instance) => {
            if (action == "confirm") {
              this.$emit("upload", file)
            } else {
              instance.close()
            }
          }
        }
      )
    },
    _getClipboardBlob(clipboard) {
      let blob, blobUrl
      for (var i = 0; i < clipboard.items.length; ++i) {
        if (
          clipboard.items[i].kind == "file" &&
          clipboard.items[i].type.indexOf("image/") !== -1
        ) {
          console.log(clipboard.items[i])
          blob = clipboard.items[i].getAsFile()
          blobUrl = (window.URL || window.webkitURL).createObjectURL(blob)
        }
      }
      return { blob, blobUrl }
    },
    shotScreen() {
      new ScreenShot({
        enableWebRtc: true, //是否启用webrtc
        level: 999999, //层级级别
        completeCallback: this.callback,
        closeCallback: this.closeShotScreen
      })
    },
    closeShotScreen() {
      console.log("关闭截图")
    },
    callback(base64data) {
      let image = new Image()
      image.src = base64data.base64
      image.onload = () => {
        let canvas = this.convertImageToCanvas(image)
        let url = canvas.toDataURL("image/jpeg")
        let bytes = window.atob(url.split(",")[1]) //通过atob将base64进行编码
        //处理异常，将ASCII码小于0的转换为大于0,进行二进制转换
        let buffer = new ArrayBuffer(bytes.length)
        let uint = new Uint8Array(buffer) //生成一个8位数的数组
        for (let i = 0; i < bytes.length; i++) {
          uint[i] = bytes.charCodeAt(i) //根据长度返回相对应的Unicode 编码
        }
        //Blob对象
        let file = new File([buffer], "screenShot" + ".jpg", {
          type: "image/jpeg"
        }) //type为图片的格式

        console.log(file)
      }
    },
    convertImageToCanvas(image) {
      let canvas = document.createElement("canvas")
      canvas.width = image.width
      canvas.height = image.height
      canvas.getContext("2d").drawImage(image, 0, 0)
      return canvas
    },
    _handleChangeFile(e) {
      const { fileInput } = this.$refs
      Array.from(fileInput.files).forEach(async (file) => {
        this.$emit("upload", file)
      })
      fileInput.value = ""
    },
    handleEmojiClick(emoji) {
      this.chatArea.insertHtml(
        `<img width='32px' height='32px' src='${emoji}' />`
      )
      this.$refs.emojiPopover.doClose()
      this._checkSubmitDisabled()
    },
    handleToolClick(e) {
      switch (e) {
        case "folder":
          this.selectFile("*")
          break
        case "scissors":
          this.shotScreen()
          break
        case "time":
          this.$emit("historyShowChange")
          break
        default:
          break
      }
    },
    async selectFile(accept) {
      this.accept = accept
      await this.$nextTick()
      this.$refs.fileInput.click()
    },
    updateUserList() {
      const memberList = this.currentGroupMemberList
        .map(({ avatar, ...rest }) => {
          return {
            avatar:
              avatar && avatar.includes("jat-im/avatar/")
                ? // eslint-disable-next-line no-undef
                  minioEndpoint_mini + avatar + "!24x24"
                : "",
            ...rest
          }
        })
        .filter((item) => item.id !== this.userInfo.id)
      this.chatArea.updateConfig({
        userList: memberList
      })
    }
  },
  watch: {
    currentGroupMemberList: {
      handler() {
        this.updateUserList()
      },
      deep: true
    }
  }
}
</script>
<style lang="less" scoped>
/deep/.chat-rich-text .chat-tag .at-user {
  color: rgb(var(--color-primary)) !important;
}
.emoji_box {
  display: flex;
  flex-wrap: wrap;
  .emoji-svg {
    padding-top: 5px !important;
  }
  .emoji_item {
    margin: 5px;
    img {
      width: 32px;
    }
    cursor: pointer;
    &:hover {
      img {
        transform: translateZ(0) scale(1.2);
      }
    }
  }
}
.chat-editor {
  display: flex;
  flex-direction: column;
  .chat-editor__tool {
    display: flex;
    align-items: center;
    margin: 5px;
    font-size: 26px;

    .icon {
      cursor: pointer;
      color: #878d99;
      margin: 6px;
      &:hover {
        color: rgba(var(--color-primary));
      }
    }
    height: 28px;
    > div {
      margin: 10px 5px;
      cursor: pointer;
      width: 28px;
      height: 28px;
    }
  }

  .chat-editor__inner {
    margin: 0px 10px;
    .chat-editor__input {
      height: 70px;
      outline: none;
      overflow-y: auto;
      /deep/.chat-rich-text {
        height: 100% !important;
        padding: 0px !important;
      }
    }
  }

  .chat-editor__footer {
    display: flex;
    justify-content: flex-end;
    padding: 5px 10px;
    align-items: center;
    .chat-editor__tip {
      padding-right: 5px;
      font-size: 12px;
      color: #999;
    }
  }
  position: relative;
  .disabled-info_box {
    position: absolute;
    width: 100%;
    height: 100%;
    background: #f1f1f1;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #999;
  }
}
</style>
